/*************************************************************
 * File: HibernateEvictCacheHandler.java
 * Copyright (c) 2012
 * Author: Huang Shaobin
 * Email: Shaobin.Software@gmail.com Shaobin_Software@163.com 
 * Date: Feb 10, 2013
 * Description: 
 ************************************************************/

package snow.core.persistence.hibernate;

import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Cache;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

import snow.core.toolkit.HttpHelper;
import snow.core.toolkit.security.Cryptogram;

/**
 * 清除Hibernate二级缓存
 * 
 * @author Shaobin.Software@gmail.com Shaobin_Software@163.com
 * @version 1.0
 */
public class HibernateEvictCacheHandler implements InitializingBean {

	private final Log log = LogFactory.getLog(getClass());

	private SessionFactory sessionFactory;

	private Set<String> evictCacheUrls;

	public void afterPropertiesSet() throws Exception {
		Assert.notNull(sessionFactory, "The property [sessionFactory] must not be null!");
		if (CollectionUtils.isNotEmpty(evictCacheUrls)) {
			for (String evictCacheUrl : evictCacheUrls) {
				final URL url = new URL(evictCacheUrl);
				Assert.isTrue("http".equalsIgnoreCase(url.getProtocol()), "[" + evictCacheUrl + "] must be a valid HTTP address!");
			}
		} else {
			evictCacheUrls = Collections.emptySet();
		}
	}

	public void evictEntity(Class<?> entityClass, Serializable identifier) {
		if (entityClass != null) {
			evictEntity(entityClass.getName(), identifier);
		}
	}

	public void evictEntity(String entityName, Serializable identifier) {
		final Cache cache = sessionFactory.getCache(); // 获取Hibernate二级缓存信息
		if (cache.containsEntity(entityName, identifier)) { // 判断缓存是否存在
			cache.evictEntity(entityName, identifier); // 清楚指定缓存
			String entityClassParam = null;
			String identifierParam = null;
			try {
				entityClassParam = URLEncoder.encode(Cryptogram.encodeByBase64(entityName), "utf-8");
			} catch (UnsupportedEncodingException e) {
				log.error(e.getMessage(), e);
			}
			final String parameters = "entityClass=" + StringUtils.trimToEmpty(entityClassParam) + "&identifier=" + StringUtils.trimToEmpty(identifierParam);
			for (String evictCacheUrl : evictCacheUrls) {
				final String url = new StringBuilder(StringUtils.length(evictCacheUrl) + parameters.length() + 1).append(evictCacheUrl).append('?').append(
						parameters).toString();
				final DeleteMethod method = new DeleteMethod(url);
				final int code = HttpHelper.execute(method);
				if (log.isDebugEnabled()) {
					try {
						log.debug("调用[" + url + "]HTTP响应代码为：" + code + "，响应信息为：" + method.getResponseBodyAsString());
					} catch (IOException e) {
						log.error(e.getMessage(), e);
					}
				}
			}
		}
	}

	public Set<String> getEvictCacheUrls() {
		return this.evictCacheUrls;
	}

	public SessionFactory getSessionFactory() {
		return this.sessionFactory;
	}

	public void setEvictCacheUrls(Set<String> evictCacheUrls) {
		this.evictCacheUrls = evictCacheUrls;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
}
